package com.fezs.web.mvc.aop;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.fezs.common.utils.JsonUtils;
import com.fezs.web.mvc.utils.WebServletUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Map;

@Slf4j
@Aspect
public class ControllerAop {

    @Pointcut("@within(org.springframework.web.bind.annotation.RestController) || @within(org.springframework.stereotype.Controller)")
    public void controllerPointcut() {}

    @Around("controllerPointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        long nowTime = System.currentTimeMillis();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        // 从HttpServletRequest获取query param
        StringBuilder params = new StringBuilder();
        Map<String, String[]> paramsMap = request.getParameterMap();
        for (String key : paramsMap.keySet()) {
            String[] values = paramsMap.get(key);
            for (String value : values) {
                params.append(key).append("=").append(value).append("&");
            }
        }

        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        // json参数，特殊处理
        if (WebServletUtils.isJsonRequest(request)) {
            if (ArrayUtil.isNotEmpty(method.getParameters())) {
                for (int i = 0; i < method.getParameters().length; i++) {
                    String key = signature.getParameterNames()[i];
                    Object arg = pjp.getArgs()[i];
                    if (arg instanceof ServletRequest || arg instanceof ServletResponse) {
                        continue;
                    }
                    String value = JsonUtils.toJsonString(arg);
                    params.append(key).append("=").append(value).append("&");
                }
            }
        }

        if (StrUtil.isNotEmpty(params)) {
            params.deleteCharAt(params.length() - 1);
        }

        // 请求的IP
        String uri = request.getMethod() + ":" + request.getRequestURI();
        String serviceName = method.getDeclaringClass().getSimpleName() + "." + method.getName();
        String ip = WebServletUtils.getClientIP(request);

        Object result = null;
        try {
            log.info("http服务开始--->uri:[{}], 方法:{}, ip:{}, 参数:{}", uri, serviceName, ip, params);
            result = pjp.proceed(pjp.getArgs());
        } finally {
            log.info("http服务结束--->耗时:{}ms, uri:[{}], 方法:{}, ip:{}, 参数:{}, 结果:{}",
                (System.currentTimeMillis() - nowTime),
                uri,
                serviceName,
                ip,
                params,
                StrUtil.subPre(JsonUtils.toJsonString(result), 500)
            );
        }
        return result;
    }

}
